package br.com.NoTraffic.com;

import javax.comm.*;
import java.io.*;

//classe Principal
public class SCom implements Runnable, SerialPortEventListener {
	// propriedades
	private String Porta;
	public String Dadoslidos;
	public int nodeBytes;
	private int baudrate;
	private int timeout;
	private CommPortIdentifier cp;
	private SerialPort porta;
	private OutputStream saida;
	private InputStream entrada;
	private Thread threadLeitura;
	// indicadores
	private boolean IDPortaOK; // true porta EXISTE
	private boolean PortaOK;// true porta aberta
	private boolean Leitura;
	private boolean Escrita;

	// construtor default paridade : par
	// baudrate: 9600 bps stopbits: 2 COM 1
	public SCom() {
		Porta = "COM1";
		baudrate = 9600;
		timeout = 1000;
	};

	// um Objeto ComObj é passado ao construtor
	// com detalhes de qual porta abrir
	// e informações sobre configurações
	public SCom(String p, int b, int t) {
		this.Porta = p;
		this.baudrate = b;
		this.timeout = t;
	};

	// habilita escrita de dados
	public void HabilitarEscrita() {
		Escrita = true;
		Leitura = false;
	}

	// habilita leitura de dados
	public void HabilitarLeitura() {
		Escrita = false;
		Leitura = true;
	}

	// Obtém o ID da PORTA
	public void ObterIdDaPorta() {
		try {
			cp = CommPortIdentifier.getPortIdentifier(Porta);
			if (cp == null) {
				System.out.println("A " + Porta + " nao existe!");
				System.out.println("ERRO!Abortando...");
				IDPortaOK = false;
				System.exit(1);
			}
			IDPortaOK = true;
		} catch (Exception e) {
			System.out.println("Erro durante o procedimento. STATUS" + e);
			IDPortaOK = false;
			System.exit(1);
		}
	}

	// Abre a comunicação da porta
	public void AbrirPorta() {
		try {
			porta = (SerialPort) cp.open("SComm", timeout);
			PortaOK = true;
			System.out.println("Porta aberta com sucesso!");
			// configurar parâmetros
			porta.setSerialPortParams(baudrate, porta.DATABITS_8,
					porta.STOPBITS_2, porta.PARITY_NONE);
		} catch (Exception e) {
			PortaOK = false;
			System.out.println("Erro ao abrir a porta! STATUS: " + e);
			System.exit(1);
		}
	}

	// função que envie um bit para a porta serial
	public void EnviarUmaString(String msg) {
		if (Escrita == true) {
			try {
				saida = porta.getOutputStream();
				System.out.println("FLUXO OK!");
			} catch (Exception e) {
				System.out.println("Erro.STATUS: " + e);
			}
			try {
				System.out.println("Enviando um byte para " + Porta);
				System.out.println("Enviando : " + msg);
				saida.write(msg.getBytes());
				Thread.sleep(100);
				saida.flush();
			} catch (Exception e) {
				System.out.println("Houve um erro durante o envio. ");
				System.out.println("STATUS: " + e);
				System.exit(1);
			}
		} else {
			System.exit(1);
		}
	}

	// leitura de dados na serial
	public void LerDados() {
		if (Escrita == true) {
			try {
				entrada = porta.getInputStream();
				System.out.println("FLUXO OK!");
			} catch (Exception e) {
				System.out.println("Erro.STATUS: " + e);
				System.exit(1);
			}
			try {
				porta.addEventListener(this);
				System.out.println("SUCESSO. Porta aguardando...");
			} catch (Exception e) {
				System.out.println("Erro ao criar listener: ");
				System.out.println("STATUS: " + e);
				System.exit(1);
			}
			porta.notifyOnDataAvailable(true);
			try {
				threadLeitura = new Thread(this);
				threadLeitura.start();
			} catch (Exception e) {
				System.out.println("Erro ao iniciar leitura: " + e);
			}
		}
	}

	// método RUN da thread de leitura
	public void run() {
		try {
			Thread.sleep(5000);
		} catch (Exception e) {
			System.out.println("Erro. Status = " + e);
		}
	}

	// gerenciador de eventos de leitura na serial
	public void serialEvent(SerialPortEvent ev) {
		switch (ev.getEventType()) {
		case SerialPortEvent.BI:
		case SerialPortEvent.OE:
		case SerialPortEvent.FE:
		case SerialPortEvent.PE:
		case SerialPortEvent.CD:
		case SerialPortEvent.CTS:
		case SerialPortEvent.DSR:
		case SerialPortEvent.RI:
		case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
			break;
		case SerialPortEvent.DATA_AVAILABLE:
			byte[] bufferLeitura = new byte[20];
			try {
				while (entrada.available() > 0) {
					nodeBytes = entrada.read(bufferLeitura);
				}
				String Dadoslidos = new String(bufferLeitura);
				if (bufferLeitura.length == 0) {
					System.out.println("Nada lido!");
				} else if (bufferLeitura.length == 1) {
					System.out.println("Apenas um byte foi lido!");
				} else {
					System.out.println(Dadoslidos);
				}
			} catch (Exception e) {
				System.out.println("Erro durante a leitura: " + e);
			}
			System.out.println("n.o de bytes lidos : " + nodeBytes);
			break;
		}
	}

	// função que fecha a conexão
	public void FecharCom() {
		try {
			porta.close();
			System.out.println("CONEXAO FECHADA>>FIM..");
		} catch (Exception e) {
			System.out.println("ERRO AO FECHAR. STATUS: " + e);
			System.exit(0);
		}
	}

	// Acessores
	public String obterPorta() {
		return Porta;
	}

	public int obterBaudrate() {
		return baudrate;
	}
}